From 7a3edfd9d043130deb49d09d54af024e95f03876 Mon Sep 17 00:00:00 2001 From: tsteven4 <13596209+tsteven4@users.noreply.github.com> Date: Fri, 27 Jan 2023 06:48:04 -0700 Subject: [PATCH] convert geo to Format class. (#998) This also adds the encoding attribute to the xml declaration. This also starts the loc element at the beginning of a line. Previously we jumped through some hoops to avoid the above two changes so we could exaclty match the original reference file. We also pass the writer to the waypt_disp_all callback via a lambda. This allows the output File and QXmlStreamWriter to be local which simplified cleanup. --- CMakeLists.txt | 1 + geo.cc | 112 +++++++++++++++-------------------------------- geo.h | 76 ++++++++++++++++++++++++++++++++ reference/gl.loc | 3 +- vecs.cc | 3 +- 5 files changed, 117 insertions(+), 78 deletions(-) create mode 100644 geo.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d65981698..ea6100cc3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -223,6 +223,7 @@ set(HEADERS geocache.h geojson.h globalsat_sport.h + geo.h gpx.h grtcirc.h gtrnctr.h diff --git a/geo.cc b/geo.cc index 4144cf036..37dd6c627 100644 --- a/geo.cc +++ b/geo.cc @@ -17,43 +17,23 @@ */ +#include "geo.h" + #include // for QByteArray #include // for QIODevice #include // for QString, operator==, QStringView::to... #include // for QStringView -#include // for QVector #include // for QXmlStreamAttributes -#include // for QXmlStreamReader -#include // for QXmlStreamWriter, QXmlStreamReader::... #include // for qPrintable, QIODeviceBase::ReadOnly #include "defs.h" -#include "gbfile.h" // for gbfclose, gbfopen, gbfputs, gbfile #include "geocache.h" // for Geocache, Geocache::container_t, Geo... #include "src/core/file.h" // for File -static char* deficon = nullptr; -static char* nuke_placer; -static gbfile* ofd; -static QString ostring; -static QXmlStreamWriter writer(&ostring); - -static -QVector geo_args = { - {"deficon", &deficon, "Default icon name", nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr }, - {"nuke_placer", &nuke_placer, "Omit Placer name", nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr }, -}; - #define MYNAME "geo" -// This really should be class-local... -static QXmlStreamReader reader; -static QString geo_read_fname; - -static Geocache::container_t wpt_container(const QString&); - -static void GeoReadLoc() +void GeoFormat::GeoReadLoc(QXmlStreamReader& reader) const { Waypoint* wpt = nullptr; QString current_tag; @@ -104,30 +84,33 @@ static void GeoReadLoc() } } -static void -geo_rd_init(const QString& fname) +void GeoFormat::rd_init(const QString& fname) +{ + geo_fname = fname; +} + +void GeoFormat::rd_deinit() { - geo_read_fname = fname; + geo_fname.clear(); } -static void -geo_read() +void GeoFormat::read() { - gpsbabel::File file(geo_read_fname); - file.open(QIODevice::ReadOnly); - reader.setDevice(&file); + gpsbabel::File ifile = gpsbabel::File(geo_fname); + ifile.open(QIODevice::ReadOnly); + QXmlStreamReader reader = QXmlStreamReader(&ifile); - GeoReadLoc(); + GeoReadLoc(reader); if (reader.hasError()) { fatal(MYNAME ":Read error: %s (%s, line %ld, col %ld)\n", qPrintable(reader.errorString()), - qPrintable(file.fileName()), + qPrintable(ifile.fileName()), (long) reader.lineNumber(), (long) reader.columnNumber()); } } -Geocache::container_t wpt_container(const QString& args) +Geocache::container_t GeoFormat::wpt_container(const QString& args) { Geocache::container_t v; @@ -160,33 +143,17 @@ Geocache::container_t wpt_container(const QString& args) return v; } -static void -geo_rd_deinit() -{ -} - -static void -geo_wr_init(const QString& fname) +void GeoFormat::wr_init(const QString& fname) { - ofd = gbfopen(fname, "w", MYNAME); - - //writer.setAutoFormatting(true); - writer.setAutoFormattingIndent(0); - writer.writeStartDocument(); - + geo_fname = fname; } -static void -geo_wr_deinit() +void GeoFormat::wr_deinit() { - writer.writeEndDocument(); - gbfputs(ostring,ofd); - gbfclose(ofd); - ofd = nullptr; + geo_fname.clear(); } -static void -geo_waypt_pr(const Waypoint* waypointp) +void GeoFormat::geo_waypt_pr(const Waypoint* waypointp, QXmlStreamWriter& writer) { writer.writeStartElement(QStringLiteral("waypoint")); @@ -252,29 +219,22 @@ geo_waypt_pr(const Waypoint* waypointp) writer.writeEndElement(); } -static void -geo_write() +void GeoFormat::write() { + gpsbabel::File ofile = gpsbabel::File(geo_fname); + ofile.open(QIODevice::WriteOnly | QIODevice::Text); + QXmlStreamWriter writer = QXmlStreamWriter(&ofile); + + writer.setAutoFormatting(true); + writer.setAutoFormattingIndent(0); + writer.writeStartDocument(); writer.writeStartElement(QStringLiteral("loc")); writer.writeAttribute(QStringLiteral("version"), QStringLiteral("1.0")); - // TODO: This could be moved to wr_init, but the pre GPX version put the two - // lines above this, so mimic that behaviour exactly. - writer.setAutoFormatting(true); writer.writeAttribute(QStringLiteral("src"), QStringLiteral("EasyGPS")); - waypt_disp_all(geo_waypt_pr); - writer.writeEndElement(); + auto geo_waypt_pr_lambda = [this, &writer](const Waypoint* waypointp)->void { + geo_waypt_pr(waypointp, writer); + }; + waypt_disp_all(geo_waypt_pr_lambda); + writer.writeEndElement(); // loc + writer.writeEndDocument(); } - -ff_vecs_t geo_vecs = { - ff_type_file, - { (ff_cap)(ff_cap_read | ff_cap_write), ff_cap_none, ff_cap_none }, - geo_rd_init, - geo_wr_init, - geo_rd_deinit, - geo_wr_deinit, - geo_read, - geo_write, - nullptr, - &geo_args, - NULL_POS_OPS -}; diff --git a/geo.h b/geo.h new file mode 100644 index 000000000..8545c6c10 --- /dev/null +++ b/geo.h @@ -0,0 +1,76 @@ +/* + Copyright (C) 2002 Robert Lipe, robertlipe+source@gpsbabel.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + */ +#ifndef GEO_H_INCLUDED_ +#define GEO_H_INCLUDED_ + +#include // for QString +#include // for QVector +#include // for QXmlStreamReader +#include // for QXmlStreamWriter + +#include "defs.h" +#include "format.h" // for Format +#include "geocache.h" // for Geocache, Geocache::container_t + + +class GeoFormat : public Format +{ +public: + QVector* get_args() override + { + return &geo_args; + } + + ff_type get_type() const override + { + return ff_type_file; + } + + QVector get_cap() const override + { + return { (ff_cap)(ff_cap_read | ff_cap_write), ff_cap_none, ff_cap_none }; + } + + void rd_init(const QString& fname) override; + void read() override; + void rd_deinit() override; + void wr_init(const QString& fname) override; + void write() override; + void wr_deinit() override; + +private: + + /* Member Functions */ + + void GeoReadLoc(QXmlStreamReader& reader) const; + void geo_waypt_pr(const Waypoint*, QXmlStreamWriter& writer); + static Geocache::container_t wpt_container(const QString&); + + /* Data Members */ + + char* deficon = nullptr; + char* nuke_placer{}; + QString geo_fname; + + QVector geo_args = { + {"deficon", &deficon, "Default icon name", nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr }, + {"nuke_placer", &nuke_placer, "Omit Placer name", nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr }, + }; +}; +#endif // GEO_H_INCLUDED_ diff --git a/reference/gl.loc b/reference/gl.loc index 192d169f2..724a8b7ec 100644 --- a/reference/gl.loc +++ b/reference/gl.loc @@ -1,4 +1,5 @@ - + + diff --git a/vecs.cc b/vecs.cc index e49c7ba7b..1007d3315 100644 --- a/vecs.cc +++ b/vecs.cc @@ -47,6 +47,7 @@ #include "gdb.h" // for GdbFormat #include "geojson.h" // for GeoJsonFormat #include "globalsat_sport.h" // for GlobalsatSportFormat +#include "geo.h" // for GeoFormat #include "gpx.h" // for GpxFormat #include "gtrnctr.h" // for GtrnctrFormat #include "html.h" // for HtmlFormat @@ -115,7 +116,7 @@ struct Vecs::Impl { #if CSVFMTS_ENABLED XcsvFormat xcsv_fmt; #endif // CSVFMTS_ENABLED - LegacyFormat geo_fmt {geo_vecs}; + GeoFormat geo_fmt; GpxFormat gpx_fmt; LegacyFormat garmin_fmt {garmin_vecs}; GdbFormat gdb_fmt; -- 2.30.2